############################################################  
#Copyright (c) 2007 Glaucio Melo (a.k.a Proteu Alcebidiano).  
#Permission is hereby granted, free of charge,    
#to any person obtaining a copy of this software and    
#associated documentation files (the "Software"),    
#to deal in the Software without restriction, including without limitation    
#the rights to use, copy, modify, merge, publish, distribute, sublicense,    
#and/or sell copies of the Software, and to permit persons to whom the    
#Software is furnished to do so, subject to the following conditions:  
  
#The above copyright notice and this permission notice shall be included in    
#all copies or substantial portions of the Software.  
  
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,    
#EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES    
#OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.    
#IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    
#DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  
#TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE    
#OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
###########################################################  
  
#xmi_parser.rb  
#since: Jan 21, 2007.  
#author: Glaucio Melo (a.k.a Proteu Alcebidiano).  
# Distributed under MIT License: <a href='http://www.opensource.org/licenses/mit-license.php'>http://www.opensource.org/licenses/mit-license.php</a>  
#This script is used to get some infomations about XMI documents. It generates an ruby object    
# from Diagram Classes (XMI files). It's useful for help in scaffold generators from XMI files.    
require "rexml/document"    
  
#Realizes the parser of xmi files and put in a hash structure.  
class XmiParser  
  attr_reader :nodes  
  
  #pre-defined xmi identifier.  
  Xmi_id = "xmi.id"    
  
  #Constructor for XmiParser. Invokes the file's content into an hash structure.    
  def initialize file_name  
      content = REXML::Document.new File.open(file_name)  
      @nodes = {}  
      load_nodes content  
  end  
  
  #Walks on the file's content and populate the item tag attributes  
  #If a tag has yor own id, we get the xmi.id as a key. Otherwise, it's used the tag's name.    
  def walk_tree values  
    attributes = values.attributes.each {|k, j|}  
    id = attributes[Xmi_id]  
    if !id.nil?  
      @nodes[id] = attributes  
    else  
      @nodes[values.name] = attributes  
    end  
  end  
  
  #Loads the file content recursively. And populates into a hash the node values.  
  #This methods do not group the content in hierarquic way. It's focused just in the tag's content  
  def load_nodes content  
    content.elements.each { |values| walk_tree values;  load_nodes values; }  
  end  
  
  #Returns the content of a node. If node equals to nil value, all node are shown.  
  def show_node node  
    result = ""    
    @nodes.each do |k,j|    
      if node == nil || k.match(node)  
         result += k + "\n\t";  
         j.each { |a, b| result += a + ":"+b + "\n\t"}  
         result += "\n"    
      end  
    end  
    result  
  end  
  
  #Loads in another hash the results of the load field. Similar of method show_mode, but the results    
  #Of this one is put on memory in similar way that show_mode does.  
  def load_field node  
    result = {}  
    @nodes.each {|k,j| result[k] = j if k.match(node)}    
    result  
  end  
  
  #Loads Xmi Files by an attribute condition that is linked by a node. Example:  
  # load_field_condition "UMLAttribute",  "owner", "UMLClass.3" returns the Attributes of UMLClass.3  
  def load_field_condition node, key, value  
    result = {}  
    @nodes.each {|k,j| result[k] = j if k.match(node) && j[key] == value}    
    result  
  end  
  
  #Returns just the key name of the hole file.  
  def show_all_key_nodes  
    result = ""    
    @nodes.each {|k, j| result += k + "\n"}  
    result  
  end  
  
  #Gets the value of an specific attribute from a node.  
  def get_value node, field  
    result = @nodes[value]  
    result[field]  
  end  
  
  #Returns all nodes informations and your attributes.  
  def to_s  
    show_node nil  
  end  
  
end  
  
#Invokes XmiParser methods.  
def execute  
  #Quick Methods' execution  
  xmi = XmiParser.new("project.xml")
  xmi.load_field "UMLClass"
  puts xmi
  puts xmi.show_node("UMLClass")
  puts xmi.show_all_key_nodes
  puts xmi.load_field_condition("UMLAttribute",  "owner", "UMLClass.3");
end  
  
#here we go! =)  
execute